package com.itheima.aspect;

import com.itheima.mapper.OperateLogMapper;
import com.itheima.pojo.OperateLog;
import com.itheima.utils.ThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * @Description LogAspect
 * @Author songyu
 * @Date 2025-01-13  17:55
 */
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor //lombok提供构造器注入注解，要求注入的成员使用final修饰，lombok自动根据final生成构造器
public class LogAspect {

    private final OperateLogMapper operateLogMapper;//注意：final修饰，不要写autowried


    //目标使用环绕通知对所有Mapper里面增、删、改方法进行数据库日志记录操作
    @Around("execution(* com.itheima.mapper.*.save*(..)) || " +
            "execution(* com.itheima.mapper.*.update*(..)) || " +
            "execution(* com.itheima.mapper.*.insert*(..)) || " +
            "execution(* com.itheima.mapper.*.delete*(..)) || " +
            "@annotation(com.itheima.anno.LogOperator)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        log.info("开始重要操作日志记录工作。。。");

        //1.实例日志对象
        OperateLog operateLog = new OperateLog();

        //2.封装数据
        //操作人ID(登录人id)
        operateLog.setOperateEmpId(getCurrentLoginId());
        //操作时间(系统当前时间)
        operateLog.setOperateTime(LocalDateTime.now());
        //操作类名，语法：pjp.getTarget().getClass().getName();
        operateLog.setClassName(pjp.getTarget().getClass().getName());
        //操作方法名:pjp.getSignature().getName()
        operateLog.setMethodName(pjp.getSignature().getName());
        //操作方法参数:pjp.getArgs()得到一个数组，转换为字符串
        operateLog.setMethodParams(Arrays.toString(pjp.getArgs()));
        //定义执行开始毫秒数
        Long start = System.currentTimeMillis();
        //执行原有方法
        Object result = pjp.proceed();
        //操作方法返回值
        operateLog.setReturnValue(result==null?null:result.toString());
        //定义执行结束毫秒数
        Long end = System.currentTimeMillis();
        //操作耗时（结束毫秒数-开始毫秒数）
        operateLog.setCostTime(end-start);

        //3.调用日志mapper执行插入数据
        operateLogMapper.operateLogInsert(operateLog);

        return result;
    }

    //获取当前登录员工id
    private Integer getCurrentLoginId() {

        //方案1：使用request读取请求头中的token,解析载荷里面存储的员工id
        //     【不好，切面方法运行一次解析一次token，存在大量重复解析token,性能不好】

        //方案2：使用ThreadLocal解决
        //打印当前线程id
        System.out.println("LogAspect: 当前线程id="+Thread.currentThread().getId());

       //return 409;
       // 从当前线程局部变量中获取登录人id
       return ThreadLocalUtil.getLoginId();
    }

}
